package org.robot.scm.infra;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.pojos.config.base.BasePlatform;
import org.robot.scm.pojos.enums.PlatformEnum;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @Author : Awn create on 2023/8/5 14:44
 */
@Slf4j
public class RedisCacheHelper {

    private static final JedisPool jedisPool;

    static {
        BasePlatform platform = AbstractMonitor.mainConfig.getPlatform(PlatformEnum.REDIS);
        String[] ipPort = platform.getNoticeSrc().split(":");
        JedisPoolConfig poolConfig = new JedisPoolConfig();

        // 最大连接数，包括使用中的和空闲的
        poolConfig.setMaxTotal(platform.getMaxTotal());
        // 最大空闲连接数，达到此数量后，额外的连接将会被释放，而不是等待闲置
        poolConfig.setMaxIdle(platform.getMaxIdle());
        // 最小空闲连接数，连接池至少应保持的数量，即使没有使用中的连接
        poolConfig.setMinIdle(platform.getMinIdle());
        // 在从池中借取连接前，是否对连接进行验证操作。这可以防止拿到无效的连接
        poolConfig.setTestOnBorrow(true);
        // 在返回连接到池前，是否对连接进行验证。有助于确保归还给池的是有效连接
        poolConfig.setTestOnReturn(true);
        // 在空闲时检查连接是否仍可用，如果不可用则从池中移除。有助于维护池的健康状态
        poolConfig.setTestWhileIdle(true);
        // 空闲连接检测周期（毫秒），配合 testWhileIdle 使用
        poolConfig.setTimeBetweenEvictionRunsMillis(60000); // 例如，每30秒检查一次
        // 空闲连接最小空闲时间（毫秒），超过此时间且空闲的连接将会被移除
        poolConfig.setMinEvictableIdleTimeMillis(30000); // 例如，5分钟内空闲会被移除
        // 当连接耗尽时，客户端从池中获取连接的最大等待时间（毫秒），超时抛出异常
        //poolConfig.setMaxWaitMillis(5000); // 例如，最大等待10秒
        // 是否在从池中取出连接时进行显式地逐出连接（false-不逐出，直到超时；true-立即逐出）
        poolConfig.setBlockWhenExhausted(false); // 当池耗尽时抛出异常，而不是阻塞
        jedisPool = new JedisPool(poolConfig, ipPort[0], Integer.parseInt(ipPort[1]), 5000, platform.getToken());
    }

    public synchronized static Jedis instance() {
        try (Jedis jedis = jedisPool.getResource()) {
            if (!jedis.isConnected()) {
                jedis.connect();
            }
            return jedis;
        } catch (Exception e) {
            throw new RuntimeException("Failed to get Jedis instance", e);
        }
    }

    public static void put(String key, String value) {
        instance().set(key, value);
    }

    public static void put(String key, String value, int seconds) {
        instance().setex(key, seconds, value);
    }

    public static String get(String key) {
        return instance().get(key);
    }


    public static Long ttl(String key) {
        return instance().pttl(key);
    }

    public static void remove(String key) {
        instance().del(key);
    }

    public static void remove(String... keys) {
        for (String key : keys) {
            instance().del(key);
        }
    }

    public static Jedis getInstance() {
        return instance();
    }
}
